//== SAGITTARIUS ============================================================================

//== BEGINNING OF CODE ===============================================================

#include "sagittarius/core/SagittariusCore.h"
#include "sagittarius/mod/modloader.h"
#include "sagittarius/session/session.h"
#include "sagittarius/io/io.h"
#include <string.h>
#include <malloc.h>

void sml_grow_modloader(sg_mod_loader* ml) {
    if(ml->n) {
        sg_module** m = malloc((ml->n+1)*sizeof(sg_module*));
        memcpy(m, ml->m, (++ml->n)*sizeof(sg_module*));
        free(ml->m);
        ml->m = m;
    } else {
        ml->m = malloc(sizeof(sg_module*));
        ++ml->n;
    }
}
/*
sg_module* sml_load_module(sg_mod_loader* ml, symcode s) {
    sg_module* m;
    sml_grow_modloader(ml);
}*/

sg_mod_loader* sg_create_mod_loader() {
    sg_mod_loader* ml = malloc(sizeof(sg_mod_loader));
    ml->t = (sg_type*)sg_global_session()->bt->modld;
    ml->n = 0;
    return ml;
}

void sg_release_mod_loader(sg_mod_loader* ml) {
    uint64 i;
    for(i=0;i<ml->n;++i)
        sg_release_module(ml->m[i]);
    free(ml);
}

sg_module* sg_mod_init(sg_module* m) {
    m->load_mod((sg_value*)m);
    m->live = 1;
    return m;
}

sg_module* sg_mod_prepare(sg_module* m) {
    SG_WRITE(2, "sg_mod_prepare\n");
    if(!m->live)
        return sg_mod_init(m);
    else
        return m;
}

void sg_register_mod(sg_mod_loader* ml, sg_module* m) {
    // does not protect agains double-registering
    sml_grow_modloader(ml);
    ml->m[ml->n-1] = m;
}

sg_module* sml_fetch_module(sg_mod_loader* x, symcode s) {
    uint64 i;
    SG_WRITE(2, "sml_fetch_module\n");
    //sg_writeUInt64(2, x->n);
    for(i=0;i<x->n;++i) {
        if(x->m[i]->s == s)
            return sg_mod_prepare(x->m[i]);
    }
    //return sml_load_module(x,s);
    AN(0, "Missing module");
    return NULL;
}

sg_value* sg_fetch_module(sg_value* mdld, symcode s) {
    sg_mod_loader* ml = (sg_mod_loader*)mdld;
    sg_module* m;
    SG_WRITE(2, "sg_fetch_module\n");
    AT(ml->t == (sg_type*)sg_global_session()->bt->modld, "Wrong type for mod loader");
    m = sml_fetch_module(ml, s);
    return (sg_value*)m;
}